home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 1.toast / Sample Code / Archive / Graphics / QuickDraw GX / GX->PostScript Sample / GXToPostScript / Imaging Engine / StylePrimitives.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-09-28  |  25.1 KB  |  935 lines  |  [TEXT/MPS ]

  1. /*
  2.      File:        StylePrimitives.c
  3.  
  4.      Contains:    QuickDraw GX to PostScript conversion code.
  5.                          File contains routines for translating various
  6.                         style attributes into PostScript
  7.  
  8.      Version:    Technology:    Quickdraw GX 1.1.x
  9.       
  10.      Copyright:    © 1991-1997 by Apple Computer, Inc., all rights reserved.
  11. */
  12.  
  13. #include "GXToPSBuildConfig.h"
  14. #include <GXGraphics.h>
  15. #include "GXGraphicsPriv.h"
  16. #include <GXEnvironment.h>
  17. #include "GXToPostScript.h"
  18. #include "IOUtilities.h"
  19. #include "RDUtil.h"
  20. #include "PublicPostScriptIE.h"
  21. #include "private.h"
  22. #include "PSIEResources.h"
  23. #include "GXErrors.h"
  24.  
  25. #ifdef resumeLabel
  26.     #undef resumeLabel
  27. #endif
  28. #define resumeLabel(exception)
  29.  
  30.  
  31.  
  32. //<FF>
  33. /*******************************
  34.  
  35.     GetPSDashPhase:
  36.     
  37.     Converts the phase from the dash record
  38.     into the appropriate value for PostScript.
  39.     
  40.     gx graphics phases are fractions of the advance into the path,
  41.     PostScript phases are distances into the dash
  42.     
  43. *********************************/
  44. Fixed GetPSDashPhase(gxDashRecord *theDash);
  45. Fixed GetPSDashPhase(gxDashRecord *theDash)
  46.     {
  47.         register Fixed     thePhase;
  48.     
  49.         thePhase = FractMultiply(theDash->advance, theDash->phase);
  50.     
  51.         return(-thePhase);            // negate because PS is into dash and gx graphics is into path.
  52.     
  53.     }//GetPSDashPhase
  54.  
  55. //<FF>
  56. #define FRACROOT2less1    444758426
  57. #define ROOT2less1 FractToFixed(FRACROOT2less1)
  58. #define fixOneHalf    ((Fixed) 0x00008000)    /* fixed 0.5 */
  59. /************************************
  60.     TestCapsRound:
  61.     
  62.     start, end:        the start and end cap shapes
  63.     
  64.     To pass the test:
  65.         each path must be a path such that
  66.                 contours = 1;
  67.                 #points in each contour = 6;
  68.                 first and last point of each is on curve, rest are off:
  69.                 
  70.                 
  71.                 For start
  72.                     
  73.                     x1 = 0, y1 =-0.5
  74.                     x2 = -(sqrt(2) - 1)/2, y2 = -0.5
  75.                     x3 = -0.5, y3 = -(sqrt(2) - 1)/2
  76.                     x4 = -0.5, y4 = (sqrt(2) - 1)/2
  77.                     x5 = -(sqrt(2) - 1)/2, y5 = 0.5
  78.                     x6 = 0, y6 = 0.5
  79.                     
  80.                 
  81.                 For End 
  82.                     mirror version of above (x's are negated)
  83.     
  84. *************************************/
  85. Boolean TestCapsRound(gxShape start, gxShape end);
  86. Boolean TestCapsRound(gxShape start, gxShape end)
  87.     {
  88.         OSErr            status;
  89.         Ptr                inStartPath;
  90.         Ptr                inEndPath;
  91.         gxPoint*    pPoint;
  92.         long            cBitsStart, cBitsEnd;
  93.         Boolean        isRound = false;
  94.         long            size;
  95.  
  96.  
  97.         /** Make sure the paths are in a known direction to minimize checks **/
  98.         
  99.         if (GXGetShapeDirection(start, 1) == gxClockwiseDirection)        // We want start-cap counter-clockwise.
  100.             GXReverseShape(start, 1);
  101.             
  102.         if (GXGetShapeDirection(end, 1) == gxCounterclockwiseDirection)        // We want end-cap clockwise.
  103.             GXReverseShape(end, 1);
  104.                                             
  105.  
  106.     
  107.         GXSetShapeAttributes(start, gxDirectShape);
  108.         GXSetShapeAttributes(end, gxDirectShape);
  109.         
  110.         GXLockShape(start);
  111.         GXLockShape(end);
  112.         inStartPath = (Ptr)GXGetShapeStructure(start, &size);
  113.         inEndPath = (Ptr)GXGetShapeStructure(end, &size);
  114.         
  115.         status = GXGetGraphicsError(nil);
  116.         nrequire(status, failed_GetShape);
  117.  
  118.         if ( (*(long*)inStartPath == 1) && (*(long*)inEndPath == 1) ) {
  119.         
  120.             /** Skip past number of contours, now at #points in contour **/
  121.             inStartPath += sizeof(long);
  122.             inEndPath += sizeof(long);
  123.  
  124.             if ( (*(long*)inStartPath == 6) && (*(long*)inEndPath == 6)) {
  125.             
  126.                 inStartPath += sizeof(long);            // Skip past #points in contour
  127.                 inEndPath += sizeof(long);
  128.                 
  129.                 cBitsStart = *(long*)inStartPath;                // Get start-cap control bits.
  130.                 cBitsEnd = *(long*)inEndPath;                        // Get end-cap control bits.
  131.                 
  132.                 if ( (cBitsStart == 0x78000000) && (cBitsEnd == 0x78000000)) {
  133.                 
  134.                     inStartPath += sizeof(long);                    // Skip past control bits.
  135.                     inEndPath += sizeof(long);
  136.  
  137.                     pPoint = (gxPoint*)inStartPath;
  138.                     if ((pPoint->x != 0) || (pPoint->y != -fixOneHalf))
  139.                         goto IsNotRound;
  140.                     
  141.                     ++pPoint;
  142.                     if ((pPoint->x != -(ROOT2less1 >> 1)) || (pPoint->y != -fixOneHalf))
  143.                         goto IsNotRound;
  144.                         
  145.                     ++pPoint;
  146.                     if ((pPoint->x != -fixOneHalf) || (pPoint->y != -(ROOT2less1 >> 1)))
  147.                         goto IsNotRound;
  148.                         
  149.                     ++pPoint;
  150.                     if ((pPoint->x != -fixOneHalf) || (pPoint->y != (ROOT2less1 >> 1)))
  151.                         goto IsNotRound;
  152.                     
  153.                     ++pPoint;
  154.                     if ((pPoint->x != -(ROOT2less1 >> 1)) || (pPoint->y != fixOneHalf))
  155.                         goto IsNotRound;
  156.                     
  157.                     ++pPoint;
  158.                     if ((pPoint->x != 0) || (pPoint->y != fixOneHalf))
  159.                         goto IsNotRound;
  160.                     
  161.                     /** Check end cap **/
  162.                     
  163.                     pPoint = (gxPoint*)inEndPath;
  164.                     if ((pPoint->x != 0) || (pPoint->y != -fixOneHalf))
  165.                         goto IsNotRound;
  166.                     
  167.                     ++pPoint;
  168.                     if ((pPoint->x != (ROOT2less1 >> 1)) || (pPoint->y != -fixOneHalf))
  169.                         goto IsNotRound;
  170.                         
  171.                     ++pPoint;
  172.                     if ((pPoint->x != fixOneHalf) || (pPoint->y != -(ROOT2less1 >> 1)))
  173.                         goto IsNotRound;
  174.                         
  175.                     ++pPoint;
  176.                     if ((pPoint->x != fixOneHalf) || (pPoint->y != (ROOT2less1 >> 1)))
  177.                         goto IsNotRound;
  178.                     
  179.                     ++pPoint;
  180.                     if ((pPoint->x != (ROOT2less1 >> 1)) || (pPoint->y != fixOneHalf))
  181.                         goto IsNotRound;
  182.                     
  183.                     ++pPoint;
  184.                     if ((pPoint->x != 0) || (pPoint->y != fixOneHalf))
  185.                         goto IsNotRound;
  186.  
  187.  
  188.                     
  189.                     isRound = true;
  190.                         
  191.                 }//end if
  192.                 
  193.             }//end if
  194.             
  195.         }//end if
  196.         
  197.             
  198. IsNotRound:
  199. failed_GetShape:
  200.  
  201.         GXUnlockShape(start);
  202.         GXUnlockShape(end);
  203.  
  204.         return(isRound);    
  205.     
  206.     }//TestCapsRound;
  207.  
  208. //<FF>
  209. /****************************
  210.     GetPSLineCap:
  211.     
  212.         Determine if caps are PostScriptable
  213.         either by geometric analysis or looking
  214.         at line cap synonym tags.
  215.         
  216.     Routine checks for synonym.  Routine
  217.     also tags the style with the synonym
  218.     when it detects a PostScriptable end cap. 
  219.     This is because the routine will actually be
  220.     called twice per style.  Once in VallidateFillShape
  221.     and once when translating the Style to PostScript.
  222.     
  223.     Returns -1 if cap isn't postscriptable.
  224.     
  225. *****************************/
  226. OSErr _GetPSLineCap(gxStyle theStyle, long *psCap)
  227.     {
  228.         gxCapRecord        theCaps;
  229.         gxRectangle        startRect, endRect;
  230.         gxTag                    aTag;
  231.         long                    tagSize;
  232.         
  233.         *psCap = -1;
  234.  
  235.         GXGetStyleCap(theStyle, &theCaps);
  236.  
  237.         /* Use the synonym only if the style really has caps */
  238.         
  239.         if (GXGetStyleTags(theStyle, gxLineCapSynonymTag, 1, 1, &aTag) && ( (theCaps.startCap != nil) || (theCaps.endCap != nil) ) ) {
  240.         
  241.             /* Get the line cap synonym value */ 
  242.             
  243.             GXLockTag(aTag);
  244.             *psCap = *(long*)((char*)GXGetTagStructure(aTag, &tagSize) - tagStructureBugOffset);
  245.             GXUnlockTag(aTag);
  246.             
  247.         } else {
  248.             
  249.             /* Try to determine what kind of line cap it is */ 
  250.             
  251.             if ( (theCaps.startCap == nil) && (theCaps.endCap == nil) ) {
  252.             
  253.                 *psCap = gxButtCap;
  254.             
  255.             } else if ( (theCaps.startCap == nil) || (theCaps.endCap == nil) ) {                // one or other nil means non-PSable.
  256.             
  257.                 *psCap = -1;
  258.             
  259.             } else if (theCaps.attributes & (gxLevelStartCap | gxLevelEndCap)) {
  260.             
  261.                 *psCap = -1;            // level-cap is not PostScriptable.
  262.                 
  263.             } else {
  264.     
  265.                 /** The bounding rectangles must be -0.5 -> 0.5 by 0 -> 0.5 to be a PS cap. **/
  266.                 
  267.                 GXGetShapeBounds(theCaps.startCap, 1, &startRect);
  268.                 GXGetShapeBounds(theCaps.endCap, 1, &endRect);
  269.                 
  270.                 if ( (startRect.top == -fixOneHalf) && (startRect.bottom == fixOneHalf) &&
  271.                          (startRect.left == -fixOneHalf) && (startRect.right == 0) &&
  272.                          (endRect.top == -fixOneHalf) && (endRect.bottom == fixOneHalf) &&
  273.                          (endRect.left == 0) && (endRect.right == fixOneHalf) ) {
  274.     
  275.                     if ((GXGetShapeType(theCaps.startCap) == gxRectangleType) && (GXGetShapeType(theCaps.endCap) == gxRectangleType)) {
  276.                             
  277.                         *psCap = gxSquareCap;
  278.             
  279.                     } else if ((GXGetShapeType(theCaps.startCap) == gxPathType) && (GXGetShapeType(theCaps.endCap) == gxPathType)) {
  280.     
  281.                         if (TestCapsRound(theCaps.startCap, theCaps.endCap))
  282.                             *psCap = gxRoundCap;
  283.                     
  284.                     }//end if
  285.                                             
  286.                     
  287.                 } else {
  288.                 
  289.                     *psCap = -1;
  290.                     
  291.                 }//end if
  292.                 
  293.             
  294.             }//end if
  295.             
  296.             
  297.             /* Tag the style so next time we look at it we're faster */
  298.             
  299.             aTag = GXNewTag(gxLineCapSynonymTag, sizeof(gxLineCapSynonym), psCap);
  300.             GXSetStyleTags(theStyle, gxLineCapSynonymTag, 0, 0, 1, &aTag);
  301.             GXDisposeTag(aTag);
  302.                 
  303.         }//end if
  304.  
  305.         if (theCaps.startCap != nil)
  306.             GXDisposeShape(theCaps.startCap);
  307.             
  308.         if (theCaps.endCap != nil)
  309.             GXDisposeShape(theCaps.endCap);
  310.  
  311.         return(noErr);
  312.     
  313.     }//GetPSLineCap
  314.  
  315.  
  316.  
  317.  
  318. //<FF>
  319. /*****************************************
  320.     MakeDashDict:
  321.     
  322.     Routine takes a dash record and outputs the 
  323.     PostScript code leaving a valid dashing dictionary
  324.     on the operand stack.
  325.     
  326. ******************************************/
  327. OSErr _MakeDashDict(TIEGlobalsHdl hIEGlobals, gxDashRecord* pDash, gxStyleAttribute theAttributes)
  328.     {
  329. #pragma unused (theAttributes)
  330.         OSErr                                status;
  331.         TRDParams*                    pRDParams;
  332.         Boolean                            dolevelDash;
  333.         Boolean                            doAutoAdvance;
  334.         Boolean                            doBreakDash;
  335.                 
  336.         dolevelDash = (pDash->attributes & gxLevelDash)? true : false;
  337.         doAutoAdvance = (pDash->attributes & gxAutoAdvanceDash)? true : false;
  338.         doBreakDash = (pDash->attributes & gxBreakDash)? true : false;
  339.  
  340.         /** First leave the shape dictionary on the stack. **/
  341.         
  342.         nrequire(status = MakeShapeDict(hIEGlobals, pDash->dash, eNoGeomOptions), failed_Geometry);
  343.         
  344.         /** Make the dash dictionary **/
  345.         
  346.         pRDParams = (*hIEGlobals)->pRDParams;
  347.         pRDParams->resIndex = kMakeDashDict;
  348.         status = RDResPrintf(pRDParams, (long)doAutoAdvance, (long)dolevelDash, (long)doBreakDash, 
  349.                                                     pDash->advance, GetPSDashPhase(pDash), pDash->scale);
  350.         nrequire(status, failed_Output);
  351.  
  352. failed_Output:
  353. failed_Geometry:
  354.         return(status);
  355.     
  356.     }//MakeDashDict
  357.  
  358. //<FF>
  359. /******************************
  360.     MakePatternPostScriptable:
  361.     
  362.     Checks to see if a shape's pattern can be
  363.     rendered by our PostScript procedures (or level-II)
  364.     
  365.     It can't if the shape is evenOddFilled and the lattice
  366.     causes overlap of the pattern shapes.
  367.     
  368.     We fix this by generating a new pattern shape that contains
  369.     overlapping copies of the original pattern shape, clipped to 
  370.     the parallelogram defined by U and V.
  371.  
  372. *******************************/
  373. void MakePatternPostScriptable(gxPatternRecord *thePattern, gxStyleAttribute theAttributes)
  374.     {
  375. #pragma unused (theAttributes)
  376.  
  377.         gxShapeType     theType;
  378.         gxRectangle        theBounds;
  379.         gxShape                shapeAtU, shapeAtV, shapeAtUplusV, cellShape, newPattern;
  380.         gxMapping            mapToXY, mapToUV;
  381.         gxPoint                patternLocInUV, patternLocInXY;
  382.         gxPoint                dimensions;
  383.         short                    width, height;
  384.         Fixed                    dx, dy;
  385.         
  386.         theType = GXGetShapeType(thePattern->pattern);
  387.         
  388.         if ( (theType == gxTextType) || (theType == gxLayoutType) || (theType == gxGlyphType) ||
  389.                  (theType == gxBitmapType) )
  390.             return;
  391.         
  392.         
  393.         if (GXGetShapeFill(thePattern->pattern) != gxEvenOddFill)
  394.             return;
  395.         
  396.         /** If we got here then see if pattern shapes will overlap in lattice cells **/
  397.         
  398.         shapeAtU = GXCopyToShape(nil, thePattern->pattern);
  399.         GXMoveShape(shapeAtU, thePattern->u.x, thePattern->u.y);
  400.         
  401.         shapeAtV = GXCopyToShape(nil, thePattern->pattern);
  402.         GXMoveShape(shapeAtV, thePattern->v.x, thePattern->v.y);
  403.         
  404.         shapeAtUplusV = GXCopyToShape(nil, thePattern->pattern);
  405.         GXMoveShape(shapeAtUplusV, thePattern->v.x + thePattern->u.x, thePattern->v.y + thePattern->u.y);
  406.                 
  407.         if ( GXTouchesShape(thePattern->pattern, shapeAtU) ||
  408.                  GXTouchesShape(thePattern->pattern, shapeAtV) ||
  409.                  GXTouchesShape(thePattern->pattern, shapeAtUplusV) ||
  410.                  GXTouchesShape(shapeAtU, shapeAtV) ) {
  411.                  
  412.             GXDisposeShape(shapeAtU);
  413.             GXDisposeShape(shapeAtV);
  414.             GXDisposeShape(shapeAtUplusV);
  415.         
  416.             /** Translate the pattern shape so its bounds are within the first pattern lattice **/        
  417.         
  418.             GXGetShapeBounds(thePattern->pattern, 0, &theBounds);
  419.             
  420.             /** Make a mapping to map into pattern space **/
  421.             
  422.             mapToXY.map[0][0] = thePattern->u.x;
  423.             mapToXY.map[0][1] = thePattern->u.y;
  424.             mapToXY.map[0][2] = 0;
  425.             
  426.             mapToXY.map[1][0] = thePattern->v.x;
  427.             mapToXY.map[1][1] = thePattern->v.y;
  428.             mapToXY.map[1][2] = 0;
  429.             
  430.             mapToXY.map[2][0] = 0;
  431.             mapToXY.map[2][1] = 0;
  432.             mapToXY.map[2][2] = fract1;
  433.             
  434.             InvertMapping(&mapToUV, &mapToXY);
  435.             
  436.             patternLocInUV.x = theBounds.left;
  437.             patternLocInUV.y = theBounds.top;
  438.             
  439.             //dprintf(trace, "Starting Location: %F %F", theBounds.left, theBounds.top);
  440.             
  441.             MapPoints(&mapToUV, 1, &patternLocInUV);
  442.             
  443.             /******
  444.                 Find location of pattern shape in 0,0 pattern cell,
  445.                 fractional part of its UV coordinates.
  446.             ******/
  447.             //dprintf(trace, "Location in UV: %F %F", patternLocInUV.x, patternLocInUV.y);
  448.             
  449.             patternLocInUV.x &= 0x0000FFFF;
  450.             
  451.             patternLocInUV.y &= 0x0000FFFF;
  452.                 
  453.             //dprintf(trace, "Move Location in UV to: %F %F", patternLocInUV.x, patternLocInUV.y);
  454.             
  455.             patternLocInXY = patternLocInUV;                            // map this location back to XY space
  456.             MapPoints(&mapToXY, 1, &patternLocInXY);
  457.             
  458.             //dprintf(trace, "Moving shape by: %F %F", patternLocInXY.x, patternLocInXY.y);
  459.             
  460.             GXMoveShape(thePattern->pattern, patternLocInXY.x - theBounds.left,
  461.                                                                               patternLocInXY.y - theBounds.top);
  462.             
  463.             /** Now the pattern shape is translated as it would be when drawn in the first lattice point **/
  464.  
  465.             /** Find the pattern shape's dimensions UV space **/
  466.  
  467.             shapeAtU = GXCopyToShape(nil, thePattern->pattern);
  468.             GXMapShape(shapeAtU, &mapToUV);
  469.             GXGetShapeBounds(shapeAtU, 0, &theBounds);
  470.             GXDisposeShape(shapeAtU);
  471.             
  472.             dimensions.x = theBounds.right - theBounds.left;
  473.             dimensions.y = theBounds.bottom - theBounds.top;
  474.             width =  1 + (long)(dimensions.x >> 16) / 2;
  475.             height = 1 + (long)(dimensions.y >> 16) / 2;
  476.             
  477.             //dprintf(trace, "Width is: %d   Height is: %d", width, height);
  478.             
  479.             /***
  480.                 Make a new pattern shape that is the union of the pattern shape drawn at the
  481.                         necessary lattice points.
  482.             ****/
  483.             theBounds.left = 0;
  484.             theBounds.top = 0;
  485.             theBounds.bottom = ff(1);
  486.             theBounds.right = ff(1);
  487.             cellShape = GXNewRectangle(&theBounds);
  488.             GXMapShape(cellShape, &mapToXY);
  489.             
  490.             newPattern = GXNewShape(gxEmptyType);                                                    // Start with a new shape.
  491.             
  492.             GXGetShapeBounds(thePattern->pattern, 0, &theBounds);            // get them again, we wrote over them.
  493.             
  494.             for (dx = -ff(width); dx <= ff(width); dx += ff(1) ) {
  495.             
  496.                 for (dy = -ff(height); dy <= ff(height); dy += ff(1) ) {
  497.                             
  498.                     patternLocInXY.x = dx;
  499.                     patternLocInXY.y = dy;
  500.                     MapPoints(&mapToXY, 1, &patternLocInXY);
  501.                     
  502.                     shapeAtV = GXCopyToShape(nil, thePattern->pattern);
  503.                     GXMoveShape(shapeAtV, patternLocInXY.x, patternLocInXY.y);
  504.                     
  505.                     if (GXTouchesShape(cellShape, shapeAtV)) 
  506.                         GXSetShapeParts(newPattern, 0, 0, shapeAtV, gxBreakLeftEdit);
  507.                     
  508.                     GXDisposeShape(shapeAtV);
  509.                 
  510.                 }//end for
  511.             
  512.             }//end for
  513.             
  514.             /** Now clip the new shape to the lattice cell **/
  515.             
  516.             
  517.             GXIntersectShape(newPattern, cellShape);
  518.                         
  519.             GXDisposeShape(cellShape);
  520.             
  521.             GXDisposeShape(thePattern->pattern);
  522.             thePattern->pattern = newPattern;
  523.         
  524.         } else { //end if
  525.     
  526.             GXDisposeShape(shapeAtU);
  527.             GXDisposeShape(shapeAtV);
  528.             
  529.         }//end if
  530.     
  531.     }//MakePatternPostScriptable
  532.  
  533.  
  534.  
  535. //<FF>
  536. /*****************************************
  537.     MakePatternDict:
  538.     
  539.     Routine takes a Pattern record and outputs the 
  540.     PostScript code leaving a valid Patterning dictionary
  541.     on the operand stack.
  542.     
  543. ******************************************/
  544. OSErr _MakePatternDict(TIEGlobalsHdl hIEGlobals, gxPatternRecord* pPattern, gxStyleAttribute theAttributes)
  545.     {
  546.         OSErr                status;
  547.         TRDParams*    pRDParams;
  548.         gxPoint            phase;
  549.         Boolean            doMapPort, doPortAllign;
  550.     
  551.         MakePatternPostScriptable(pPattern, theAttributes);
  552.  
  553.         phase.x = 0;
  554.         phase.y = 0;
  555.         
  556.         /** First leave the shape dictionary on the stack. **/
  557.  
  558.         status = MakeShapeDict(hIEGlobals, pPattern->pattern, eNoGeomOptions);
  559.         nrequire(status, failed_Geometry);
  560.         
  561.         /** Make the pattern dictionary **/
  562.  
  563.         // map port if attribute set, but only for bitmap patterns, attribute ignored otherwise.        
  564.         doMapPort = ((pPattern->attributes & gxPortMapPattern) && (GXGetShapeType(pPattern->pattern) == gxBitmapType)) ? true : false;
  565.         doPortAllign = (pPattern->attributes & gxPortAlignPattern)? true : false;
  566.         
  567.         pRDParams = (*hIEGlobals)->pRDParams;
  568.         pRDParams->resIndex = kMakePatDict;
  569.         status = RDResPrintf(pRDParams, &(pPattern->u), &(pPattern->v), &phase, (long)doMapPort, (long)doPortAllign );
  570.         nrequire(status, failed_Output);
  571.  
  572. failed_Output:
  573. failed_Geometry:
  574.         return(status);
  575.     
  576.     }//MakePatternDict
  577.  
  578.  
  579.  
  580. //<FF>
  581. /**********************************************
  582.  
  583.     Routine:    DoDashSynonym:
  584.     
  585.     Routine outputs the data in a dash synonym for the SetDash operator.
  586.     operator. Data output in the form same as PostScript "setdash" operator.
  587.     
  588.     pRDParams:        Pointer to RDUtilities parameter block.
  589.     pDashSyn:            Pointer to a dash synonym record from the style.
  590.     pDash:                Pointer to the dash record from the style.
  591.     
  592. ***********************************************/
  593. OSErr DoDashSynonym(TIEGlobalsHdl hGlobals, TRDParams* pRDParams, gxDashSynonym* pDashSyn, gxDashRecord *pDash);
  594. OSErr DoDashSynonym(TIEGlobalsHdl hGlobals, TRDParams* pRDParams, gxDashSynonym* pDashSyn, gxDashRecord *pDash)
  595.     {
  596.         OSErr                            status;    
  597.         Fixed*                        pVal;
  598.         register short        i;
  599.         
  600.         /* Output the array of values onto the operand stack */
  601.         
  602.         nrequire(status = DoBeginArray(hGlobals), failed_Output);
  603.         
  604.         pRDParams->resIndex = kDoFixed;
  605.         pVal = pDashSyn->dashLength;                                        // value pointer at beginning of array.
  606.         for (i = pDashSyn->size - 1; i >= 0; --i) {
  607.         
  608.             nrequire(status = RDResPrintf(pRDParams, *pVal++), failed_Output);
  609.         
  610.         }//end for
  611.         
  612.         nrequire(status = DoEndArray(hGlobals), failed_Output);
  613.         
  614.         /** Output the phase of the dash **/
  615.         
  616.         nrequire(status = RDResPrintf(pRDParams, GetPSDashPhase(pDash)), failed_Output);
  617.         
  618.  
  619. failed_Output:    
  620.         return(status);
  621.     
  622.     }//DoDashSynonym
  623.     
  624.     
  625.  
  626. //<FF>
  627. /**********************************************
  628.     
  629.     Routine:        FrameStylePrimitive:
  630.     
  631.     Routines sets all of the style attributes in the 
  632.     PostScript graphics state associated with the frame
  633.     shape.
  634.     
  635. ***********************************************/
  636. OSErr FrameStylePrimitive(TIEGlobalsHdl hIEGlobals, gxStyle theStyle)
  637.     {
  638.         OSErr                            status = noErr;
  639.         TRDParams*                pRDParams;
  640.         TIEGlobalsPtr            pGlobals;
  641.         gxJoinRecord            theJoin;
  642.         gxDashRecord            theDash;
  643.         gxDashSynonym            *pDashSyn;
  644.         gxStyleAttribute    theAttributes;
  645.         long                            psVal;                        // enumerated postscript value for line cap and join.
  646.         Fixed                            aValue;
  647.         gxTag                            aTag;
  648.         long                            tagSize;
  649.  
  650.         
  651.         pGlobals = *hIEGlobals;
  652.         
  653.         pRDParams = pGlobals->pRDParams;
  654.         
  655.         theAttributes = GXGetStyleAttributes(theStyle);
  656.         
  657.         /** Do the frame attributes **/
  658.         psVal = GetPSFrameValue(theAttributes);
  659.         if ((psVal!= pGlobals->psFrameValue) || (pGlobals->ieStateFlags & eStyleOutOfDate)) {
  660.         
  661.             pGlobals->psFrameValue = psVal;
  662.                             
  663.             pRDParams->resIndex = kSetFrame;
  664.             nrequire(status = RDResPrintf(pRDParams, psVal), failed_Output);
  665.         
  666.             /** Refresh pointers, handle may have moved. **/
  667.             pGlobals = *hIEGlobals;
  668.             
  669.         }//end if
  670.         
  671.         
  672.         
  673.         /** Do the line Cap **/
  674.     
  675.         status = _GetPSLineCap(theStyle, &psVal);
  676.         nrequire(status, failed_Skia);
  677.  
  678.         if ((psVal != -1) && ( (pGlobals->lineCap != psVal ) || (pGlobals->ieStateFlags & eStyleOutOfDate)) ) {
  679.         
  680.             pGlobals->lineCap = psVal;
  681.             pRDParams->resIndex = kSetLineCap;
  682.             nrequire(status = RDResPrintf(pRDParams, psVal), failed_Output);
  683.  
  684.             /** Refresh pointers, handle may have moved. **/
  685.             pGlobals = *hIEGlobals;
  686.         
  687.         }//end if
  688.         
  689.         
  690.         /** Do the line width **/
  691.         
  692.         aValue = GXGetStylePen(theStyle);
  693.         if ((pGlobals->lineWidth != aValue) || (pGlobals->ieStateFlags & eStyleOutOfDate)) {
  694.         
  695.             pGlobals->lineWidth = aValue;
  696.             pRDParams->resIndex = kSetLineWidth;
  697.             nrequire(status = RDResPrintf(pRDParams, aValue), failed_Output);
  698.  
  699.             /** Refresh pointers, handle may have moved. **/
  700.             pGlobals = *hIEGlobals;
  701.             
  702.         }//end if
  703.         
  704.         /** Do the line join **/
  705.         
  706.         GXGetStyleJoin(theStyle, &theJoin);
  707.         psVal = GetPSLineJoin(&theJoin);
  708.         status = GXGetGraphicsError(nil);
  709.         nrequire(status, failed_Skia);
  710.         
  711.         if ((psVal != -1) && ( (pGlobals->lineJoin != psVal) || (pGlobals->ieStateFlags & eStyleOutOfDate)) ) {
  712.         
  713.             pGlobals->lineJoin = psVal;
  714.             pRDParams->resIndex = kSetLineJoin;
  715.             nrequire(status = RDResPrintf(pRDParams, psVal), failed_Output);
  716.  
  717.             /** Refresh pointers, handle may have moved. **/
  718.             pGlobals = *hIEGlobals;
  719.         
  720.         }//end if
  721.         
  722.  
  723.         if (theJoin.join != nil)
  724.             GXDisposeShape(theJoin.join);
  725.         
  726.         
  727.         /** Do the miter limit **/
  728.         
  729.         aValue = SkiaMiterToPS(theJoin.miter, pGlobals->lineWidth);
  730.         
  731.         if ((aValue != pGlobals->miterLimit) || (pGlobals->ieStateFlags & eStyleOutOfDate)) {
  732.                 
  733.             pGlobals->miterLimit = aValue;
  734.             pRDParams->resIndex = kSetMiterLim;
  735.             nrequire(status = RDResPrintf(pRDParams, aValue), failed_Output);
  736.         
  737.             pGlobals = *hIEGlobals;
  738.         
  739.         }//end if
  740.  
  741.  
  742.         /******
  743.                 Do the dash: 
  744.                 If there is a synonym, put its data on the stack.  If there is a dash shape 
  745.                 make a dash dictionary, put it on stack - Else put null on stack
  746.         ******/
  747.         
  748.         GXGetStyleDash(theStyle, &theDash);                            // Get the real dash record
  749.         
  750.         /* Get dashing synonym if available */
  751.         
  752.         if (GXGetStyleTags(theStyle, gxDashSynonymTag, 1, 1, &aTag) && (theDash.dash != nil)) {
  753.         
  754.             pGlobals->ieStateFlags |= eHasDash;
  755.             pGlobals->ieStateFlags &= ~eSimpleStyle;
  756.  
  757.             GXLockTag(aTag);
  758.             pDashSyn = (gxDashSynonym*)((char*)GXGetTagStructure(aTag, &tagSize) - tagStructureBugOffset);
  759.  
  760.             nrequire_action(status = DoDashSynonym(hIEGlobals, pRDParams, pDashSyn, &theDash), failed_Dash, GXUnlockTag(aTag););
  761.  
  762.             /* Do the SetDash operator */        
  763.             pRDParams->resIndex = kSetDash;
  764.             status = RDResPrintf(pRDParams);
  765.             GXUnlockTag(aTag);
  766.  
  767.             if (theDash.dash) 
  768.                 GXDisposeShape(theDash.dash);
  769.                 
  770.             nrequire(status, failed_Output);
  771.         
  772.         } else if (theDash.dash != nil) {
  773.         
  774.             pGlobals->ieStateFlags |= eHasDash;
  775.             pGlobals->ieStateFlags &= ~eSimpleStyle;
  776.         
  777.             nrequire(status = _MakeDashDict(hIEGlobals, &theDash, theAttributes), failed_Dash);
  778.                         
  779.             /* Do the SetDash operator */        
  780.             pRDParams->resIndex = kSetDash;
  781.             nrequire(status = RDResPrintf(pRDParams), failed_Output);
  782.  
  783.             GXDisposeShape(theDash.dash);
  784.                 
  785.         } else {             
  786.  
  787.             // if previous shape had dash and current one doesn't , output null for SetDash.            
  788.         
  789.             if ((pGlobals->ieStateFlags & eHasDash) || (pGlobals->ieStateFlags & eStyleOutOfDate)) {
  790.                 
  791.                 pGlobals->ieStateFlags &= ~eHasDash;
  792.                 nrequire(status = DoNull(pRDParams), failed_Output);
  793.                 
  794.                 /* Do the SetDash operator */        
  795.                 pRDParams->resIndex = kSetDash;
  796.                 nrequire(status = RDResPrintf(pRDParams), failed_Output);
  797.                 
  798.             }//end if
  799.         
  800.  
  801.         }//end if
  802.  
  803.  
  804. /** If you put any more code after here, make sure to refresh pGlobals **/            
  805.  
  806. failed_Dash:
  807. failed_Skia:
  808. failed_Output:
  809.  
  810.         
  811.         return(status);
  812.     
  813.     
  814.     }//FrameStylePrimitive
  815.  
  816.  
  817. //<FF>
  818. /**********************************************
  819.     
  820.     Routine:        MiscStylePrimitive:
  821.     
  822.     Routines sets all the attributes of the style
  823.     in the PostScript graphics state that affect
  824.     all shapes, framed or filled.
  825.     
  826.     
  827. ***********************************************/
  828. OSErr MiscStylePrimitive(TIEGlobalsHdl hIEGlobals, gxStyle theStyle)
  829.     {
  830.         OSErr                            status = noErr;
  831.         TIEGlobalsPtr            pGlobals;
  832.         TRDParams                    *pRDParams;
  833.         gxStyleAttribute    theAttributes;
  834.         Boolean                        rIsOut;
  835.         gxPatternRecord        thePattern;
  836.         Boolean                        changedPattern = false;
  837.         
  838.         
  839.         pGlobals = *hIEGlobals;
  840.         pRDParams = pGlobals->pRDParams;
  841.                 
  842.         /** Output the curve error **/
  843.  
  844.         #ifdef useCurveError
  845.             aValue = GXGetStyleCurveError(theStyle);
  846.             if ((aValue != pGlobals->curveFlat) || pGlobals->initializeGstate) {
  847.             
  848.                 pGlobals->curveFlat = aValue;
  849.                 
  850.                 pRDParams->resIndex = kSetFlat;
  851.                 status = RDResPrintf(pRDParams, aValue);
  852.                 nrequire(status, failed_Output);
  853.             
  854.                 /** Refresh pointers, handle may have moved. **/
  855.                 pGlobals = *hIEGlobals;
  856.     
  857.             }//end if
  858.         #endif        
  859.         
  860.         /** Output other style attributes **/
  861.         
  862.         theAttributes = GXGetStyleAttributes(theStyle);
  863.         rIsOut = (theAttributes & gxAutoInsetStyle);
  864.         if ((rIsOut != pGlobals->currRightIsOut) || (pGlobals->ieStateFlags & eStyleOutOfDate)) {
  865.                 
  866.             pGlobals->currRightIsOut = rIsOut;
  867.             
  868.             pRDParams->resIndex = kSetRightIsOut;
  869.             status = RDResPrintf(pRDParams, rIsOut);
  870.             nrequire(status, failed_Output);
  871.             
  872.             /** Refresh pointers, handle may have moved. **/
  873.             pGlobals = *hIEGlobals;
  874.         
  875.         }//end if
  876.         
  877.         /******* Output the pattern if there is one ************/
  878.         
  879.         GXGetStylePattern(theStyle, &thePattern);
  880.         status = GXGetGraphicsError(nil);
  881.         nrequire(status, failed_Skia);
  882.         
  883.  
  884.         /** If there is a pattern shape, make a pattern dictionary, put it on stack - Else put null on stack **/
  885.         if (thePattern.pattern != nil) {
  886.         
  887.             /** Mark persistent state as having pattern **/
  888.             pGlobals->ieStateFlags |= eHasPattern;            
  889.             
  890.             /** Patterns not simple, need to output QD2Fill **/
  891.             pGlobals->ieStateFlags &= ~eSimpleStyle;
  892.             
  893.             status = _MakePatternDict(hIEGlobals, &thePattern, theAttributes);
  894.             nrequire(status, failed_Pattern);
  895.             
  896.             changedPattern = true;
  897.                         
  898.             GXDisposeShape(thePattern.pattern);
  899.         
  900.         } else {
  901.         
  902.             // if previous shape had pattern and current one doesn't , output null SetPat.
  903.             
  904.             if ((pGlobals->ieStateFlags & eHasPattern) || (pGlobals->ieStateFlags & eStyleOutOfDate)) {
  905.             
  906.                 /** Mark persistent state as not having pattern **/
  907.                 pGlobals->ieStateFlags &= ~eHasPattern;
  908.  
  909.                 nrequire(status = DoNull(pRDParams), failed_Output);
  910.  
  911.                 changedPattern = true;
  912.                                 
  913.             }//end if
  914.                     
  915.         }//end if
  916.  
  917.         /** If we downloaded a new pattern or are changing it to null, issue the SetPat operator **/
  918.  
  919.         if (changedPattern) {
  920.         
  921.             pRDParams->resIndex = kSetPattern;
  922.             nrequire(status = RDResPrintf(pRDParams), failed_Output);
  923.         
  924.         }//end if
  925.         
  926. failed_Pattern:
  927. failed_Skia:        
  928. failed_Output:
  929.         return(status);
  930.     
  931.     }//MiscStylePrimitive
  932.     
  933.     
  934.  
  935.